/* Zatok - язык программирования текстовых игр
 * (С) 2010 - 2012 Меркулов Матвей Юрьевич
 * Код лицензирован под лицензией GNU LGPL
 * Вы можете прочитать текст лицензии по адресу:
 * http://www.gnu.org/copyleft/lesser.html
 * или прочитать русский перевод по адресу:
 * http://ru.wikisource.org/wiki/GNU_Lesser_General_Public_License
 */

package base.value.userobject;

import base.CObject;
import base.CProject;
import base.context.CCommand;
import base.context.CContext;
import base.module.CModule;
import base.value.CObjectValue;
import base.value.CValue;
import java.util.LinkedList;
import parser.CInheritance;
import parser.CParser;

public class CUserObject extends CContext {
	public int ID;
	public CBaseData BaseData;
	public LinkedList<CModule> Initialization = new LinkedList<CModule>();
	public LinkedList<CUserObject> Children = new LinkedList<CUserObject>();
	public CUserObject Parent = CProject.Null;
	protected static int LastID = 0;



	public static CUserObject Create( CBaseData BaseData ) {
		CUserObject Object = new CUserObject();
		LastID++;
		Object.ID = LastID;
		Object.BaseData = BaseData;
		return Object;
	}
	
	
	
	@Override
	public CValue GetValue() {
		return new CObjectValue( this );
	}



	@Override
	public CObject Parse( LinkedList<String> Tokens ) {
		if ( CParser.CurrentFunction != null ) CParser.Error( "Объект в блоке функции" );
		if ( CParser.CurrentCommand != null ) CParser.Error( "Объект в блоке команды " );
		
		CUserObject Object = CParser.GetObject( Tokens.get( 1 ) );
		if ( Object == null ) CParser.Error();
		
		CBaseData ObjectBaseData = Object.BaseData;
		if ( Tokens.getFirst().equals( "клонобъекта" ) ) {
			Object = CUserObject.Create( null );
			CProject.ObjectsList.add( Object );
		}
		
		CProject.CurrentObject.Children.addLast( Object );
		Object.Parent = CProject.CurrentObject;

		CInheritance OldCurrentInheritance = CParser.CurrentInheritance;
		if ( Tokens.get( Tokens.size() - 2 ).equals( "копирует" ) ) {
			if( Object.BaseData == null ) CParser.Error( "Клон объекта не может наследоваться от другого объекта" );
			CParser.CurrentInheritance = new CInheritance( CParser.GetObject( Tokens.get( Tokens.size() - 1 ) ).ToObject(), Object );
		}

		CUserObject OldCurrentObject = CProject.CurrentObject;
		CProject.CurrentObject = Object;

		while (true) {
			Tokens = CParser.ReadTokens();
			
			if ( Tokens == null ) CParser.Error( "Неожиданный конец файла в блоке объекта" );

			if ( Tokens.getFirst().equals( "конецобъекта" ) ) {
				break;
			}
			CParser.SearchForIllegalKeywords( Tokens, "КонецОбъекта" );

			if( Object.BaseData == null ) {
				AddModule( Object.Initialization, Tokens );
			} else {
				AddModule( Object.BaseData.Initialization, Tokens );
			}
		}
		
		Object.BaseData = ObjectBaseData;

		CProject.CurrentObject = OldCurrentObject;
		CParser.CurrentInheritance = OldCurrentInheritance;
		return null;
	}



	@Override
	public void Init() {
		CUserObject OldCurrentObject = CProject.CurrentObject;
		CProject.CurrentObject = this;
		CContext OldCurrentContext = CProject.CurrentContext;
		CProject.CurrentContext = null;

		//System.out.println( ID );

		CProject.ExitStatus = CProject.EExitStatus.No;
		ExecuteModulesList( BaseData.Initialization );
		ExecuteModulesList( Initialization );
		CProject.ExitStatus = CProject.EExitStatus.No;

		CProject.CurrentContext = OldCurrentContext;
		CProject.CurrentObject = OldCurrentObject;
	}
	
	

	@Override
	public boolean ToBoolean() {
		return true;
	}



	@Override
	public CUserObject ToObject() {
		return this;
	}



	public CCommand FindCommand( String Name ) {
		for ( CCommand Command : BaseData.Commands ) {
			if ( Command.Name.ToString().equals( Name ) ) return Command;
		}
		return null;
	}
	
	
	
	@Override
	public String toString() {
		return BaseData.Name[ 0 ];
	}
}
